package com.facebook.drawee.controller;

import android.content.Context;
import android.graphics.drawable.Animatable;

import com.facebook.common.internal.Preconditions;
import com.facebook.common.internal.Supplier;
import com.facebook.datasource.AbstractDataSource;
import com.facebook.datasource.FirstAvailableDataSourceSupplier;
import com.facebook.datasource.IncreasingQualityDataSourceSupplier;
import com.facebook.datasource.SimpleDataSource;
import com.facebook.drawee.components.RetryManager;
import com.facebook.drawee.gestures.GestureDetector;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.interfaces.SimpleDraweeControllerBuilder;

import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicLong;

import javax.annotation.Nullable;

public abstract class AbstractDraweeControllerBuilder<BUILDER extends AbstractDraweeControllerBuilder<BUILDER, REQUEST, IMAGE, INFO>, REQUEST, IMAGE, INFO>
        implements SimpleDraweeControllerBuilder {
    public final Context mContext;
    @Nullable
    public Object mCallerContext;
    @Nullable
    public REQUEST mLowResImageRequest;
    public boolean mTapToRetryEnabled;
    @Nullable
    public DraweeController mOldController;
    private static final ControllerListener<Object> sAutoPlayAnimationsListener = new BaseControllerListener() {
        public final void onFinalImageSet(String id, @Nullable Object imageInfo, @Nullable Animatable animatable) {
            if (animatable != null) {
                animatable.start();
            }
        }
    };
    private static final NullPointerException NO_REQUEST_EXCEPTION = new NullPointerException("No image request was specified!");
    @Nullable
    private REQUEST mImageRequest;
    @Nullable
    private REQUEST[] mMultiImageRequests;
    private boolean mTryCacheOnlyFirst;
    @Nullable
    private ControllerListener<? super INFO> mControllerListener;
    private boolean mAutoPlayAnimations;
    private static final AtomicLong sIdCounter = new AtomicLong();

    public AbstractDraweeControllerBuilder(Context context) {
        this.mContext = context;
        this.init();
    }

    public final void init() {
        this.mCallerContext = null;
        this.mImageRequest = null;
        this.mLowResImageRequest = null;
        this.mMultiImageRequests = null;
        this.mTryCacheOnlyFirst = true;
        this.mControllerListener = null;
        this.mTapToRetryEnabled = false;
        this.mAutoPlayAnimations = false;
        this.mOldController = null;
    }

    public abstract AbstractDataSource<IMAGE> getDataSourceForRequest(REQUEST request, boolean justCache);

    public final BUILDER setControllerListener(ControllerListener<? super INFO> controllerListener) {
        this.mControllerListener = controllerListener;
        return this.getThis();
    }

    public final BUILDER setOldController(@Nullable DraweeController arg2) {
        this.mOldController = arg2;
        return this.getThis();
    }

    public final BUILDER setImageRequest(REQUEST request) {
        this.mImageRequest = request;
        return this.getThis();
    }

    public final BUILDER setFirstAvailableImageRequests(REQUEST[] requests) {
        this.mMultiImageRequests = requests;
        this.mTryCacheOnlyFirst = true;
        return this.getThis();
    }

    private Supplier<AbstractDataSource<IMAGE>> getDataSourceSupplierForRequest(final REQUEST request, final boolean justCache) {
        return new Supplier<AbstractDataSource<IMAGE>>() {

            public final AbstractDataSource<IMAGE> get() {
                return AbstractDraweeControllerBuilder.this.getDataSourceForRequest(request, justCache);
            }

            public final String toString() {
                return android.support.design.a.toStringHelper(this).add("request", request.toString()).toString();
            }
        };
    }

    public final BUILDER setAutoPlayAnimations() {
        this.mAutoPlayAnimations = true;
        return this.getThis();
    }

    public final BUILDER setCallerContext(Object callerContext) {
        this.mCallerContext = callerContext;
        return this.getThis();
    }

    public final AbstractDraweeController buildController() {
        Preconditions.checkState(this.mMultiImageRequests == null || this.mImageRequest == null,
                "Cannot specify both ImageRequest and FirstAvailableImageRequests!");
        Preconditions.checkState(true, "Cannot specify DataSourceSupplier with other ImageRequests! Use one or the other.");
        if (this.mImageRequest == null && this.mMultiImageRequests == null && this.mLowResImageRequest != null) {
            this.mImageRequest = this.mLowResImageRequest;
            this.mLowResImageRequest = null;
        }
        AbstractDraweeController abstractDraweeController = this.obtainController();
        if (this.mTapToRetryEnabled) {
            RetryManager retryManager = abstractDraweeController.mRetryManager;
            if (retryManager == null) {
                retryManager = new RetryManager();
                abstractDraweeController.mRetryManager = retryManager;
            }
            retryManager.mTapToRetryEnabled = this.mTapToRetryEnabled;
            if (abstractDraweeController.mGestureDetector == null) {
                abstractDraweeController.mGestureDetector = new GestureDetector(this.mContext);
                if (abstractDraweeController.mGestureDetector != null) {
                    abstractDraweeController.mGestureDetector.mClickListener = abstractDraweeController;
                }
            }
        }
        if (this.mControllerListener != null) {
            abstractDraweeController.addControllerListener(this.mControllerListener);
        }
        if (this.mAutoPlayAnimations) {
            abstractDraweeController.addControllerListener(sAutoPlayAnimationsListener);
        }
        return abstractDraweeController;
    }

    public static String generateUniqueControllerId() {
        return String.valueOf(sIdCounter.getAndIncrement());
    }

    public final Supplier<AbstractDataSource<IMAGE>> obtainDataSourceSupplier() {
        Supplier<AbstractDataSource<IMAGE>> supplier = null;
        if (this.mImageRequest != null) {
            supplier = this.getDataSourceSupplierForRequest(this.mImageRequest, false);
        } else if (this.mMultiImageRequests != null) {
            REQUEST[] requestArr = this.mMultiImageRequests;
            ArrayList<Supplier<AbstractDataSource<IMAGE>>> arrayList = new ArrayList(requestArr.length << 1);
            if (mTryCacheOnlyFirst) {
                for (int i = 0; i < requestArr.length; ++i) {
                    arrayList.add(this.getDataSourceSupplierForRequest(requestArr[i], true));
                }
            }
            for (int i = 0; i < requestArr.length; ++i) {
                arrayList.add(this.getDataSourceSupplierForRequest(requestArr[i], false));
            }
            supplier = new FirstAvailableDataSourceSupplier(arrayList);
        }

        if (supplier != null && this.mLowResImageRequest != null) {
            ArrayList<Supplier<AbstractDataSource<IMAGE>>> arrayList = new ArrayList(2);
            arrayList.add(supplier);
            arrayList.add(this.getDataSourceSupplierForRequest(this.mLowResImageRequest, false));
            supplier = new IncreasingQualityDataSourceSupplier(arrayList);
        }

        if (supplier == null) {
            supplier = new Supplier<AbstractDataSource<IMAGE>>() {
                @Override
                public final AbstractDataSource<IMAGE> get() {
                    SimpleDataSource simpleDataSource = new SimpleDataSource();
                    simpleDataSource.setFailure(NO_REQUEST_EXCEPTION);
                    return simpleDataSource;
                }
            };
        }

        return supplier;
    }

    public abstract AbstractDraweeController obtainController();

    public abstract BUILDER getThis();

    public final DraweeController build() {
        return this.buildController();
    }
}

